package miniBanco.Handler;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.JLabel;
import javax.swing.JOptionPane;

import basics.DBManager;
import miniBanco.Core.*;
import miniBanco.Dto.*;
import miniBanco.Dto.Mapper.DTOMapper;
import miniBanco.Exceptions.HandledException;
import miniBanco.Gui.ClienteMainFrameButton;
import miniBanco.Gui.CuentasGrid;
import miniBanco.Gui.DepositoPanel;
import miniBanco.Gui.ExtraccionPanel;
import miniBanco.Gui.MovimientosGrid;
import miniBanco.Gui.TransferenciaPanel;
import miniBanco.Mapper.MapperRegistry;
import miniBanco.Mapper.Interface.IClienteFinder;
import miniBanco.Mapper.Interface.ICuentaFinder;

public class HandlerClienteMainFrame {
	Component lastComponent = null;
	HandlerMain mainHandler;
	Cliente c;
	//Components
	ClienteMainFrameButton clienteMainFrameButton;
	CuentasGrid cuentaGrid;
	ExtraccionPanel extPanel;
	DepositoPanel depoPanel;
	TransferenciaPanel tranPanel;
	//finder
	ICuentaFinder cuentaFinder;
	IClienteFinder clienteFinder;
	public HandlerClienteMainFrame(HandlerMain mainHandler,Cliente c)
	{
		cuentaFinder = MapperRegistry.GetInstance().CuentaMapper();
		clienteFinder = MapperRegistry.GetInstance().ClienteMapper();
		this.c = c;
		this.mainHandler = mainHandler;
	}
	
	private void RefreshCuentasGrid()
	{
		ArrayList<Cuenta> cuentas = (ArrayList<Cuenta>) c.getCuentas();
		ArrayList<CuentaDTO> cuentasDTO = DTOMapper.ToCuentaDtoList(cuentas);
		cuentaGrid.Refresh(cuentasDTO);
	}
	
	public void Show()
	{
		clienteMainFrameButton = new ClienteMainFrameButton();	
		cuentaGrid = new CuentasGrid();
		AgregarComponente(cuentaGrid);
		RefreshCuentasGrid();
		JLabel label = new JLabel("Bienvenido cliente:"+c.getNombre());
		mainHandler.frame.add(label,BorderLayout.NORTH);
		mainHandler.frame.add(cuentaGrid,BorderLayout.CENTER);
		mainHandler.frame.add(clienteMainFrameButton,BorderLayout.SOUTH);
		
		//Handler de los botones
		clienteMainFrameButton.getBtnVerCuentas().addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				AgregarComponente(cuentaGrid);
			}
		});
		clienteMainFrameButton.getBtnVerUltimosMovimientos().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				
				if(cuentaGrid.getTable().getSelectedRow() == -1)
				{
					JOptionPane.showMessageDialog(null, "Debe seleccionar al menos un registro");
					return;
				}			
				int row = cuentaGrid.getTable().getSelectedRow();
				CuentaDTO cuentaDTO = cuentaGrid.getData().get(row);
				Cuenta cuenta = null;
				for(Cuenta cuenta1:c.getCuentas())
				{
					if(cuenta1.getID() == cuentaDTO.getId())
						cuenta = cuenta1;
				}
				if(cuenta == null)
				{
					throw new HandledException("No encontre cuenta");
				}
				ArrayList<Movimiento> movimientos = (ArrayList<Movimiento>) cuenta.getMovimientos();
				MovimientosGrid mov = new MovimientosGrid();
				mov.Refresh(DTOMapper.ToMovimientoDtoList(movimientos));
				AgregarComponente(mov);
			}
		});		
		clienteMainFrameButton.getBtnTransferencia().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				if(cuentaGrid.getTable().getSelectedRow() == -1)
				{
					JOptionPane.showMessageDialog(null, "Debe seleccionar al menos un registro");
					return;
				}		
				int row = cuentaGrid.getTable().getSelectedRow();
				CuentaDTO cuentaDTO = cuentaGrid.getData().get(row);
				Cuenta CuentaOrigen =  c.getCuentaById(cuentaDTO.getId());
				//
				tranPanel = new TransferenciaPanel();
				tranPanel.SetInitialValues(CuentaOrigen.getID(), Integer.toString(CuentaOrigen.getNroCuenta()));
				//
				tranPanel.getButtonCuentaDestino().addActionListener(new ActionListener() {
					
					@Override
					public void actionPerformed(ActionEvent arg0) {
						// TODO Auto-generated method stub
						int cbu = tranPanel.getCuentaDestino();
						ArrayList<Cuenta> cuentaList = cuentaFinder.FindByCbu(cbu);
						if(cuentaList.size() > 0)
						{
							Cuenta cuenta = cuentaList.get(0);
							long idCuenta = cuenta.getID();
							
							String nombreCliente = c.getNombre();
							tranPanel.SetCuentaDestino(nombreCliente,idCuenta);
							return;
						}
						JOptionPane.showMessageDialog(null, "No existe la cuenta destino");
					}
				});
				tranPanel.getButtonTransferencia().addActionListener(new ActionListener() {
					
					@Override
					public void actionPerformed(ActionEvent arg0) {
						TransferenciaDTO tranDTO = tranPanel.getFormValues();
						if(tranDTO.getCuentaDestinoID() == 0)
						{
							JOptionPane.showMessageDialog(null, "Debe seleccionar una cuenta Destino valida");
							return;
						}
						if(tranDTO.getImporte() == 0)
						{
							JOptionPane.showMessageDialog(null, "El importe debe ser mayor a 0");
							return;
						}
						buttonTransferenciaOk(tranDTO.getCuentaOrigenID(),tranDTO.getCuentaDestinoID(),tranDTO.getImporte());
					}
				});
				//
				AgregarComponente(tranPanel);
			}
		});		
		clienteMainFrameButton.getBtnExtraer().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				if(cuentaGrid.getTable().getSelectedRow() == -1)
				{
					JOptionPane.showMessageDialog(null, "Debe seleccionar al menos un registro");
					return;
				}		
				int row = cuentaGrid.getTable().getSelectedRow();
				CuentaDTO cuentaDTO = cuentaGrid.getData().get(row);
				
				extPanel = new ExtraccionPanel();
				extPanel.getBtnExtraer().addActionListener(new ActionListener() {
					
					@Override
					public void actionPerformed(ActionEvent e) {
						buttonExtraerClick();
					}
				});
				ExtraccionDTO extraccionDTO = new ExtraccionDTO();
				extraccionDTO.setCuenta(Integer.toString(cuentaDTO.getCbu()));
				extraccionDTO.setIdCuenta(cuentaDTO.getId());
				extPanel.setFormValues(extraccionDTO);
				AgregarComponente(extPanel);
				
			}
		});
		clienteMainFrameButton.getBtnDepositar().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				if(cuentaGrid.getTable().getSelectedRow() == -1)
				{
					JOptionPane.showMessageDialog(null, "Debe seleccionar al menos un registro");
					return;
				}		
				int row = cuentaGrid.getTable().getSelectedRow();
				CuentaDTO cuentaDTO = cuentaGrid.getData().get(row);
				depoPanel = new DepositoPanel();
				depoPanel.getBtnDeposito().addActionListener(new ActionListener() {
					
					@Override
					public void actionPerformed(ActionEvent e) {
						buttonDepositoClick();
					}
				});
				ExtraccionDTO extraccionDTO = new ExtraccionDTO();
				extraccionDTO.setCuenta(Integer.toString(cuentaDTO.getCbu()));
				extraccionDTO.setIdCuenta(cuentaDTO.getId());
				depoPanel.setFormValues(extraccionDTO);
				AgregarComponente(depoPanel);
				}
			}
		);
	}
	private void AgregarComponente(Component c)
	{
		if(lastComponent != null)
		{
			mainHandler.frame.remove(lastComponent);
		}
		mainHandler.frame.add(c,BorderLayout.CENTER);
		lastComponent = c;
		mainHandler.frame.validate();
		mainHandler.frame.repaint();
	}
	private void buttonExtraerClick() {
		ExtraccionDTO extraccionDTO = extPanel.getFormValues();
		long idCuenta = extraccionDTO.getIdCuenta();
		Cuenta cuenta = null;
		for(Cuenta cuenta1:c.getCuentas())
		{
			if(cuenta1.getID() == idCuenta)
			{
				cuenta = cuenta1;
			}
		}
		try
		{
			cuenta.Extraer(extraccionDTO.getImporte());
			clienteFinder.doSave(c);
			RefreshCuentasGrid();
		}
		catch(HandledException ex)
		{
			JOptionPane.showMessageDialog(null, ex.getMessage());
			return;
		}
		JOptionPane.showMessageDialog(null, "Extraccion con exito");
		AgregarComponente(cuentaGrid);
	}
	private void buttonDepositoClick() {
		ExtraccionDTO extraccionDTO = depoPanel.getFormValues();
		long idCuenta = extraccionDTO.getIdCuenta();
		Cuenta cuenta = null;
		for(Cuenta cuenta1:c.getCuentas())
		{
			if(cuenta1.getID() == idCuenta)
			{
				cuenta = cuenta1;
			}
		}
		try
		{
			cuenta.Depositar(extraccionDTO.getImporte());
			clienteFinder.doSave(c);
			RefreshCuentasGrid();
		}
		catch(HandledException ex)
		{
			JOptionPane.showMessageDialog(null, ex.getMessage());
			return;
		}
		JOptionPane.showMessageDialog(null, "Deposito con exito");
		AgregarComponente(cuentaGrid);
	}	
	private void buttonTransferenciaOk(long cuentaOrigenID, long cuentaDestinoID, float importe)
	{
		
		Cuenta cuentaOrigen = cuentaFinder.find(cuentaOrigenID);
		Cuenta cuentaDestino = cuentaFinder.find(cuentaDestinoID);
		try
		{
			cuentaOrigen.TransferirDinero(cuentaDestino, importe);
			cuentaFinder.doSave(cuentaOrigen);
			cuentaFinder.doSave(cuentaDestino);			
			RefreshCuentasGrid();
		}
		catch(HandledException ex)
		{
			JOptionPane.showMessageDialog(null, ex.getMessage());
			return;
		}
		catch(Exception ex)
		{
			DBManager.Error(ex);
			JOptionPane.showMessageDialog(null,"Se produjo un error inesperado");
			return;
		}
		JOptionPane.showMessageDialog(null,"La transferencia se realizo exitosamente");
		AgregarComponente(cuentaGrid);
	}
}
